/*
 * Copyright (c) 2011, 9nali.com All rights reserved.
 */
package com.waitingsnow.core.util.core
{
import flash.utils.ByteArray;

/**
 *  The StringUtil utility class is an all-static class with methods for
 *  working with String objects.
 */
public class StringUtil
{
    //==========================================================================
    //  Class methods
    //==========================================================================

    /**
     *    Removes whitespace from the front and the end of the specified
     *    string.
     *    @param input The String whose beginning and ending whitespace will
     *    will be removed.
     *    @returns A String with whitespace removed from the begining and end
     */
    public static function trim(input:String):String
    {
        return StringUtil.ltrim(StringUtil.rtrim(input));
    }

    /**
     *    Removes whitespace from the front of the specified string.
     *    @param input The String whose beginning whitespace will will be removed.
     *    @returns A String with whitespace removed from the begining
     */
    public static function ltrim(input:String):String
    {
        var size:Number = input.length;
        for (var i:Number = 0; i < size; i++)
        {
            if (input.charCodeAt(i) > 32)
            {
                return input.substring(i);
            }
        }
        return "";
    }

    /**
     *    Removes whitespace from the end of the specified string.
     *    @param input The String whose ending whitespace will will be removed.
     *    @returns A String with whitespace removed from the end
     */
    public static function rtrim(input:String):String
    {
        var size:Number = input.length;
        for (var i:Number = size; i > 0; i--)
        {
            if (input.charCodeAt(i - 1) > 32)
            {
                return input.substring(0, i);
            }
        }
        return "";
    }

    /**
     *  Substitutes "{n}" tokens within the specified string
     *  with the respective arguments passed in.
     *
     *  @param str The string to make substitutions in.
     *  This string can contain special tokens of the form
     *  <code>{n}</code>, where <code>n</code> is a zero based index,
     *  that will be replaced with the additional parameters
     *  found at that index if specified.
     *
     *  @param rest Additional parameters that can be substituted
     *  in the <code>str</code> parameter at each <code>{n}</code>
     *  location, where <code>n</code> is an integer (zero based)
     *  index value into the array of values specified.
     *  If the first parameter is an array this array will be used as
     *  a parameter list.
     *  This allows reuse of this routine in other methods that want to
     *  use the ... rest signature.
     *  For example <pre>
     *     public function myTracer(str:String, ... rest):void
     *     {
     *         label.text += StringUtil.substitute(str, rest) + "\n";
     *     } </pre>
     *
     *  @return New string with all of the <code>{n}</code> tokens
     *  replaced with the respective arguments specified.
     *
     *  @example
     *
     *  var str:String = "here is some info "{0}" and {1}";
     *  Tracer.info(StringUtil.substitute(str, 15.4, true));
     *
     *  // this will output the following string:
     *  // "here is some info "15.4" and true"
     */
    public static function substitute(input:String, ... rest):String
    {
        // Replace all of the parameters in the msg string.
        var len:uint = rest.length;
        var args:Array;
        if (len == 1 && rest[0] is Array)
        {
            args = rest[0] as Array;
            len = args.length;
        }
        else
        {
            args = rest;
        }

        for (var i:int = 0; i < len; i++)
        {
            input = input.replace(new RegExp("\\{" + i + "\\}", "g"), args[i]);
        }
        return input;
    }

    /**
     *  Substitutes "{$id}" tokens within the specified string
     *  with the respective object arguments passed in.
     */
    public static function substituteByID(input:String, containObj:Object):String
    {
        // Replace all of the paramenters in the passed string.
        for (var i:String in containObj)
        {
            input = input.replace(new RegExp("\\{\\$" + i + "\\}", "g"), containObj[i]);
        }
        return input;
    }

    /**
     *    Replaces all instances of the replace string in the input string
     *    with the replaceWith string.
     *    @param input The string that instances of replace string will be
     *    replaces with removeWith string.
     *    @param replace The string that will be replaced by instances of
     *    the replaceWith string.
     *    @param replaceWith The string that will replace instances of replace
     *    string.
     *    @returns A new String with the replace string replaced with the
     *    replaceWith string.
     */
    public static function replace(input:String, replace:String, replaceWith:String):String
    {
        return input.split(replace).join(replaceWith);
    }

    /**
     * validate Email address
     */
    public static function validateEmail(input:String):Boolean
    {
        var pattern:RegExp =
            /^[0-9a-zA-Z][-._a-zA-Z0-9]*@([0-9a-zA-Z][-._0-9a-zA-Z]*\.)+[a-zA-Z]{2,4}$/;
        var result:Object = pattern.exec(input);
        if (result == null)
        {
            return false;
        }
        return true;
    }

    /**
     * Encoding for String
     * Change GB2312 to UTF8
     */
    public static function GB2312toUTF8(input:*):String
    {
        var byte:ByteArray = new ByteArray();
        byte.writeMultiByte(input, "gb2312");
        byte.position = 0;
        return byte.readMultiByte(byte.bytesAvailable, "utf-8");
    }

    public static function UTF8toGB2312(input:*):String
    {
        var byte:ByteArray = new ByteArray();
        byte.writeMultiByte(input, "utf-8");
        byte.position = 0;
        return byte.readMultiByte(byte.bytesAvailable, "gb2312");
    }

    /**
     * add zero padding
     */
    public static function zeroPad(num:int):String
    {
        var output:String;
        if (num < 10 && num >= 0)
        {
            output = "0" + num;
        }
        else if(isNaN(num))
        {
            output = "00";
        }
        else
        {
            output = String(num);
        }
        return output;
    }

    /**
     * 复制某一字符生成固定长度的字符串
     *
     * Example:
     * <CODE>
     * Tracer.debug("Result: "+StringUtil.multiply(">", 6); // Result: >>>>>>
     * </CODE>
     *
     * @param string 需要复制的字符
     * @param factor 复制次数
     * @return 复制好的字符
     */
    public static function multiply(string:String, factor:Number):String
    {
        var result:String="";

        for(var i:Number = factor; i>0; i--) {
            result += string;
        }
        return result;
    }

    /**
     * 对两个字符串进行比较，常用于数组中用户名，商品名等排序
     * 先比字符排序顺序，然后比字符长度
     * @return 两个字符之间相差的数字，如u1比u2大则返回正整数，反之则返回负整数，如两个字符相同则返回0
     * 比较结果:AAA>AAa>aAA>Bbb>bBB>CCCc>CCC
     */
    public static function compareStr(u1:String, u2:String):int
    {
        var len1:int = u1.length;
        var len2:int = u2.length;
        var len:int = Math.min(len1, len2);
        for (var i:int = 0; i < len; ++i)
        {
            var c1:String = u1.charAt(i);
            var c2:String = u2.charAt(i);
            var r1:int = c1.toLocaleLowerCase().localeCompare(c2.toLocaleLowerCase());
            if (r1 != 0)
            {
                return r1;
            }

            var r2:int = c1.localeCompare(c2);
            if (r2 != 0)
            {
                return r2;
            }
        }
        return len1 - len2;
    }

    /**
     * 限制字符串长度，超过指定长度的剩余字符将被切除，然后再加上"..."
     * @param value 将被操作的字符串
     * @param len 需限制的长度(英数为1个单位，中文及其它符号为2个单位)
     * @return String (如"my name is...")
     *
     */
    public static function restrictLength(value:String, len:uint):String
    {
        var size:uint = 0;
        var strLength:uint = value.length;
        for(var i:uint = 0; i < value.length; i++)
        {
            if (value.charCodeAt(i) > 0x7FF)
            {
                size += 2;
            }
            else
            {
                size++ ;
            }
            if (size > len)
            {
                break;
            }
        }
        if (i < strLength)
        {
            value = value.slice(0, i);
            value += "...";
        }
        return value;
    }
}
}
